home *** CD-ROM | disk | FTP | other *** search
- /* Routines common to both the FTP client and server
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by G1EMM */
- /* Mods by KO4KS */
- #include "global.h"
- #include "mbuf.h"
- #include "socket.h"
- #include "ftp.h"
- #include "ftpcli.h"
- #include "usock.h"
- #include "md5.h"
-
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: ftpsubr.c,v 1.12 1996/12/23 22:44:37 root Exp root $";
- #endif
-
- #define MD5BLOCK 64 /* Preferred MD5 block size */
-
- int md5hash (FILE * fp, char hash[16], int ascii);
- static void hashit (int hash, long total, long *hmark, int sent);
-
-
- static void
- hashit (hash, total, hmark, sent)
- int hash;
- long total, *hmark;
- int sent;
- {
- while (hash && total >= (*hmark) + 1000) {
- if (hash == V_HASH)
- tputc ('#');
- if (hash == V_BYTE)
- tprintf ("Bytes %s : %ld\r", (sent) ? "sent" : "received", total);
- *hmark += 1000;
- }
-
- }
-
-
- /* Send a file (opened by caller) on a network socket.
- * Normal return: count of bytes sent
- * Error return: -1
- * re-written by KO4KS to (1) reduce code size (2) all binary compression
- */
- long
- sendfile (fp, s, mode, hash)
- register FILE *fp; /* File to be sent */
- register int s; /* Socket to be sent on */
- int mode; /* Transfer mode */
- int hash; /* Print hash marks every BLKSIZE bytes */
- {
- register int c;
- register long total = 0;
- long hmark = 0;
- int oldf = 0;
- struct usock *up;
- register struct mbuf *bp;
-
- if (mode == ASCII_TYPE) {
- oldf = setflush (s, -1);
- /* Let the newline mapping code in usputc() do the work */
- (void) sockmode (s, SOCK_ASCII);
- } else
- (void) sockmode (s, SOCK_BINARY);
- up = itop (s);
- if (mode != ASCII_TYPE && up->zout == NULLLZW) { /* also, not lzw compressed */
- for (;;) {
- kwait (0); /* be a good neighbor and share! */
- bp = ambufw (BLKSIZE);
- if ((bp->cnt = (int16) fread (bp->data, 1, BLKSIZE, fp)) == 0) {
- free_p (bp);
- break;
- }
- kwait (0); /* be a good neighbor and share! */
- total += bp->cnt;
- if (send_mbuf (s, bp, 0, NULLCHAR, 0) == -1) {
- total = -1;
- break;
- }
- hashit (hash, total, &hmark, 1);
- }
- } else {
-
- /* At this point, it is either ASCII_TYPE, or LZW compressed */
- while ((c = getc (fp)) != EOF) {
- if (mode == ASCII_TYPE) {
- #ifndef TNOS_68K
- #if !defined(UNIX) && !defined(__TURBOC__)
- if (c == '\r') {
- /* Needed only if the OS uses a CR/LF
- * convention and getc doesn't do
- * an automatic translation
- */
- continue;
- }
- #endif
- #else
- if (c == '\l')
- continue;
- #endif
- if (!c)
- continue;
- }
- if (usputc (s, uchar (c)) == -1) {
- total = -1;
- break;
- }
- total++;
- hashit (hash, total, &hmark, 1);
- if (!(total % 256))
- kwait (0); /* be a good neighbor and share! */
- }
- }
- if (mode == ASCII_TYPE) {
- usflush (s);
- (void) setflush (s, oldf);
- }
- if (hash)
- tputc ('\n');
- return total;
- }
-
-
- /* Receive a file (opened by caller) from a network socket.
- * Normal return: count of bytes received
- * Error return: -1
- * re-written by KO4KS to (1) reduce code size (2) all binary compression
- */
- long
- recvfile (fp, s, mode, hash)
- register FILE *fp;
- register int s;
- int mode;
- int hash;
- {
- register int c;
- register long total = 0;
- long hmark = 0;
- int cnt;
- struct usock *up;
- struct mbuf *bp;
-
- if (mode == ASCII_TYPE)
- (void) sockmode (s, SOCK_ASCII);
- else
- (void) sockmode (s, SOCK_BINARY);
- up = itop (s);
- if (mode != ASCII_TYPE && up->zout == NULLLZW) { /* also, not lzw compressed */
- while ((cnt = recv_mbuf (s, &bp, 0, NULLCHAR, 0)) != 0) {
- kwait (0); /* be a good neighbor and share! */
- if (cnt == -1) {
- total = -1;
- break;
- }
- total += cnt;
- hashit (hash, total, &hmark, 0);
- kwait (0); /* be a good neighbor and share! */
- if (fp != NULLFILE) {
- if (write_p (fp, bp) == -1) {
- free_p (bp);
- total = -1;
- break;
- }
- free_p (bp);
- } else
- (void) send_mbuf (Curproc->output, bp, 0, NULLCHAR, 0);
- kwait (0); /* be a good neighbor and share! */
- }
- } else {
- while ((c = recvchar (s)) != EOF) {
- if (fp != NULLFILE) {
- #if !defined(UNIX) && !defined(__TURBOC__)
- if (mode == ASCII_TYPE) {
- if (c == '\n') {
- /* Needed only if the OS uses a CR/LF
- * convention and putc doesn't do
- * an automatic translation
- */
- (void) putc ('\r', fp);
- }
- }
- #endif
- if (putc (c, fp) == EOF) {
- total = -1;
- break;
- }
- } else
- tputc (uchar (c));
- total++;
- hashit (hash, total, &hmark, 0);
- if (!(total % 256))
- kwait (0); /* be a good neighbor and share! */
- }
- }
- /* Detect an abnormal close */
- if (socklen (s, 0) == -1)
- total = -1;
- if (hash)
- tputc ('\n');
- return total;
- }
-
-
- /* Determine if a file appears to be binary (i.e., non-text).
- * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
- *
- * Used by FTP to warn users when transferring a binary file in text mode.
- */
- int
- isbinary (fp)
- FILE *fp;
- {
- int c, i;
- int rval;
-
- rval = 0;
- for (i = 0; i < 512; i++) {
- if ((c = getc (fp)) == EOF)
- break;
- if (c & 0x80) {
- /* High bit is set, probably not text */
- rval = 1;
- break;
- }
- }
- /* Assume it was at beginning */
- fseek (fp, 0L, SEEK_SET);
- return rval;
- }
-
-
- unsigned long
- getsize (fp)
- FILE *fp;
- {
- fseek (fp, 0L, SEEK_END); /* Go to end of file */
- return (unsigned long) ftell (fp); /* Return file pointer position */
- }
-
-
- /* Compute checksum of the first n bytes */
- unsigned long
- checksum (fp, n)
- FILE *fp;
- long n;
- {
- unsigned long sum;
- long i;
- int c;
-
- rewind (fp);
- sum = 0;
- for (i = 1; i <= n; i++) {
- if ((c = fgetc (fp)) == EOF)
- break;
- sum += (unsigned long) c;
- }
- return sum;
- }
-
-
- /* Compute MD5 hash of local file */
- int
- md5hash (fp, hash, ascii)
- FILE *fp;
- char hash[16];
- int ascii;
- {
- MD5_CTX md;
- char *buf;
- int len;
-
- MD5Init (&md);
-
- if (ascii) {
- /* Text file, hash canonical form (newlines = crlf) */
- char *cp;
- int c;
-
- cp = buf = mallocw (MD5BLOCK);
- len = 0;
- while ((c = fgetc (fp)) != EOF) {
- if (c == '\n') {
- *cp++ = '\r';
- if (++len == MD5BLOCK) {
- MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
- kwait (NULL);
- cp = buf;
- len = 0;
- }
- }
- *cp++ = (char) c;
- if (++len == MD5BLOCK) {
- MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
- kwait (NULL);
- cp = buf;
- len = 0;
- }
- }
- if (len != 0)
- MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
- free (buf);
- } else {
- buf = mallocw (BUFSIZ);
- while ((len = (int) fread (buf, 1, BUFSIZ, fp)) != 0) {
- MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
- kwait (NULL);
- }
- free (buf);
- }
- MD5Final (&md);
- memcpy (hash, md.digest, 16);
- return 0;
- }
-